; (function ($, window) {
    let ele = null,
        exzoom_img_box = null,
        boxWidth = null,
        boxHeight = null,
        exzoom_img_ul_outer = null,//鐢ㄤ簬闄愬埗 ul 瀹藉害,鍙堜笉褰卞搷鏀惧ぇ闀滃尯鍩�
        exzoom_img_ul = null,
        exzoom_img_ul_position = 0,//寰幆鍥剧墖鍖哄煙鐨勮竟璺�,鐢ㄤ簬绉诲姩鏃惰窡闅忓厜鏍�
        exzoom_img_ul_width = 0,//寰幆鍥剧墖鍖哄煙鐨勬渶澶у搴�
        exzoom_img_ul_max_margin = 0,//寰幆鍥剧墖鍖哄煙鐨勬渶澶у杈硅窛,搴旇鏄浘鐗囨暟閲忓噺涓€涔樹互boxWidth
        exzoom_nav = null,
        exzoom_nav_inner = null,
        navHightClass = "current",//褰撳墠鍥剧墖鐨勭被,
        exzoom_navSpan = null,
        navHeightWithBorder = null,
        images = null,
        exzoom_prev_btn = null,//瀵艰埅涓婁竴寮犲浘鐗�
        exzoom_next_btn = null,//瀵艰埅涓嬩竴寮犲浘鐗�
        imgNum = 0,//鍥剧墖鐨勬暟閲�
        imgIndex = 0,//褰撳墠鍥剧墖鐨勭储寮�
        imgArr = [],//鍥剧墖灞炴€х殑鏁板瓧
        exzoom_zoom = null,
        exzoom_main_img = null,
        exzoom_zoom_outer = null,
        exzoom_preview = null,//棰勮鍖哄煙
        exzoom_preview_img = null,//棰勮鍖哄煙鐨勫浘鐗�
        autoPlayInterval = null,//鐢ㄤ簬鎺у埗鑷姩鎾斁鐨勯棿闅旀椂闂�
        startX = 0,//绉诲姩鍏夋爣鐨勮捣濮嬪潗鏍�
        startY = 0,//绉诲姩鍏夋爣鐨勮捣濮嬪潗鏍�
        endX = 0,//绉诲姩鍏夋爣鐨勭粓姝㈠潗鏍�
        endY = 0,//绉诲姩鍏夋爣鐨勭粓姝㈠潗鏍�
        g = {},//鍏ㄥ眬鍙橀噺
        defaults = {
            "navWidth": 60,//鍒楄〃姣忎釜瀹藉害,璇ョ増鏈腑璇锋妸瀹介珮濉啓鎴愪竴鏍�
            "navHeight": 60,//鍒楄〃姣忎釜楂樺害,璇ョ増鏈腑璇锋妸瀹介珮濉啓鎴愪竴鏍�
            "navItemNum": 5,//鍒楄〃鏄剧ず涓暟
            "navItemMargin": 7,//鍒楄〃闂撮殧
            "navBorder": 1,//鍒楄〃杈规锛屾病鏈夎竟妗嗗～鍐�0锛岃竟妗嗗湪css涓慨鏀�
            "autoPlay": true,//鏄惁鑷姩鎾斁
            "autoPlayTimeout": 2000,//鎾斁闂撮殧鏃堕棿
        };


    let methods = {
        init: function (options) {
            let opts = $.extend({}, defaults, options);

            ele = this;
            exzoom_img_box = ele.find(".exzoom_img_box");
            exzoom_img_ul = ele.find(".exzoom_img_ul");
            exzoom_nav = ele.find(".exzoom_nav");
            exzoom_prev_btn = ele.find(".exzoom_prev_btn");//缂╃暐鍥惧鑸笂涓€寮犳寜閽�
            exzoom_next_btn = ele.find(".exzoom_next_btn");//缂╃暐鍥惧鑸笅涓€寮犳寜閽�

            //todo 浠ュ悗鍙互鍒嗗紑瀹藉害鍜岄珮搴︾殑闄愬埗
            boxHeight = boxWidth = ele.outerWidth();  //鍦ㄥ皬灞忓箷涓�,鏈� padding 鐨勬儏鍐典笅,璁＄畻涓嶅噯,闇€瑕佹墜鍔ㄦ寚瀹� ele 鐨勫搴�

            // console.log("boxWidth::" + boxWidth);
            // console.log("ele.parent().width()::" + ele.parent().width());
            // console.log("ele.parent().outerWidth()::" + ele.parent().outerWidth());
            // console.log("ele.parent().innerWidth()::" + ele.parent().innerWidth());

            //todo 缂╃暐鍥惧鑸殑楂樺害鍜屽搴﹀彲浠ユ敼涓烘牴鎹� 瀵艰埅鏍忓搴� 鍜� navItemNum 璁＄畻鍑烘潵,浣嗘槸瀵逛簬涓嶅悓灏哄鐨勪笉濂藉鐞�
            g.navWidth = opts.navWidth;
            g.navHeight = opts.navHeight;
            g.navBorder = opts.navBorder;
            g.navItemMargin = opts.navItemMargin;
            g.navItemNum = opts.navItemNum;
            g.autoPlay = opts.autoPlay;
            g.autoPlayTimeout = opts.autoPlayTimeout;

            images = exzoom_img_box.find("img");
            imgNum = images.length;//鍥剧墖鐨勬暟閲�
            checkLoadedAllImages(images)//妫€鏌ュ浘鐗囨槸鍚﹀仴鍦ㄥ畬鎴�,鍏ㄩ儴鍔犺浇瀹屾垚鐨勪細鎵ц鍒濆鍖�
        },
        prev: function () {             //涓婁竴寮犲浘鐗�
            moveLeft()
        },
        next: function () {            //涓嬩竴寮犲浘鐗�
            moveRight();
        },
        setImg: function () {            //璁剧疆澶у浘
            let url = arguments[0];

            getImageSize(url, function (width, height) {
                exzoom_preview_img.attr("src", url);
                exzoom_main_img.attr("src", url);

                //todo 鏈祴璇�
                //鍒ゆ柇宸叉湁鐨勫浘鐗囨暟閲忔槸鍚﹀悎鏈€鍒濈殑涓€鑷�,涓嶆槸鐨勮瘽灏卞厛鍒犻櫎鏈€鍚庝竴涓�
                if (exzoom_img_ul.find("li").length === imgNum + 1) {
                    exzoom_img_ul.find("li:last").remove();
                }
                exzoom_img_ul.append('<li style="width: ' + boxWidth + 'px;">' +
                    '<img src="' + url + '"></li>');

                let image_prop = copute_image_prop(url, width, height);
                previewImg(image_prop);
            });
        },
    };

    $.fn.extend({
        "exzoom": function (method, options) {
            if (arguments.length === 0 || (typeof method === 'object' && !options)) {
                if (this.length === 0) {
                    // alert("璋冪敤 jQuery.exzomm 鏃剁殑閫夋嫨鍣ㄤ负绌�");
                    $.error('Selector is empty when call jQuery.exzomm');
                } else {
                    return methods.init.apply(this, arguments);
                }
            } else if (methods[method]) {
                return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
            } else {
                // alert("璋冪敤浜� jQuery.exzomm 涓笉瀛樺湪鐨勬柟娉�");
                $.error('Method ' + method + 'does not exist on jQuery.exzomm');
            }
        }
    });

    /**
     * 鍒濆鍖�
     */
    function init() {
        exzoom_img_box.append("<div class='exzoom_img_ul_outer'></div>");
        exzoom_nav.append("<p class='exzoom_nav_inner'></p>");
        exzoom_img_ul_outer = exzoom_img_box.find(".exzoom_img_ul_outer");
        exzoom_nav_inner = exzoom_nav.find(".exzoom_nav_inner");

        //鎶� exzoom_img_ul 绉诲姩鍒� exzoom_img_ul_outer 閲�
        exzoom_img_ul_outer.append(exzoom_img_ul);

        //寰幆鎵€鏈夊浘鐗�,璁＄畻灏哄,娣诲姞缂╃暐鍥惧鑸�
        for (let i = 0; i < imgNum; i++) {
            imgArr[i] = copute_image_prop(images.eq(i));//璁板綍鍥剧墖鐨勫昂瀵稿睘鎬х瓑
            console.log(imgArr[i]);
            let li = exzoom_img_ul.find("li").eq(i);
            li.css("width", boxWidth);//璁剧疆鍥剧墖涓婄骇鐨� li 鍏冪礌鐨勫搴�
            li.find("img").css({
                "margin-top": imgArr[i][5],
                "width": imgArr[i][3]
            });
        }

        //缂╃暐鍥惧鑸�
        exzoom_navSpan = exzoom_nav.find("span");
        navHeightWithBorder = g.navBorder * 2 + g.navHeight;
        g.exzoom_navWidth = (navHeightWithBorder + g.navItemMargin) * g.navItemNum;
        g.exzoom_nav_innerWidth = (navHeightWithBorder + g.navItemMargin) * imgNum;

        exzoom_navSpan.eq(imgIndex).addClass(navHightClass);
        exzoom_nav.css({
            "height": navHeightWithBorder + "px",
            "width": boxWidth - exzoom_prev_btn.width() - exzoom_next_btn.width(),
        });
        exzoom_nav_inner.css({
            "width": g.exzoom_nav_innerWidth + "px"
        });
        exzoom_navSpan.css({
            "margin-left": g.navItemMargin + "px",
            "width": g.navWidth + "px",
            "height": g.navHeight + "px",
        });

        //璁剧疆婊氬姩鍖哄煙鐨勫搴�
        exzoom_img_ul_width = boxWidth * imgNum;
        exzoom_img_ul_max_margin = boxWidth * (imgNum - 1);
        exzoom_img_ul.css("width", exzoom_img_ul_width);
        //娣诲姞鏀惧ぇ闀�
        exzoom_img_box.append(`
<div class='exzoom_zoom_outer'>
    <span class='exzoom_zoom'></span>
</div>
<p class='exzoom_preview'>
    <img class='exzoom_preview_img' src='' />
</p>
            `);
        exzoom_zoom = exzoom_img_box.find(".exzoom_zoom");
        exzoom_main_img = exzoom_img_box.find(".exzoom_main_img");
        exzoom_zoom_outer = exzoom_img_box.find(".exzoom_zoom_outer");
        exzoom_preview = exzoom_img_box.find(".exzoom_preview");
        exzoom_preview_img = exzoom_img_box.find(".exzoom_preview_img");

        //璁剧疆澶у浘鍜岄瑙堝浘鍖哄煙
        exzoom_img_box.css({
            "width": boxHeight + "px",
            "height": boxHeight + "px",
        });

        exzoom_img_ul_outer.css({
            "width": boxHeight + "px",
            "height": boxHeight + "px",
        });

        exzoom_preview.css({
            "width": boxHeight + "px",
            "height": boxHeight + "px",
            "left": boxHeight + 5 + "px",//娣诲姞涓竟璺�
        });

        previewImg(imgArr[imgIndex]);
        autoPlay();//鑷姩鎾斁
        bindingEvent();//缁戝畾浜嬩欢
    }

    /**
     * 妫€娴嬪浘鐗囨槸鍚﹀姞杞藉畬鎴�
     * @param images
     */
    function checkLoadedAllImages(images) {
        let timer = setInterval(function () {
            let loaded_images_counter = 0;
            let all_images_num = images.length;
            images.each(function () {
                if (this.complete) {
                    loaded_images_counter++;
                }
            });
            if (loaded_images_counter === all_images_num) {
                clearInterval(timer);
                init();
            }
        }, 100)
    }

    /**
     * 鑾峰彇鍏夋爣鍧愭爣,濡傛灉鏄� touch 浜嬩欢,鍙鐞嗙涓€涓�
     */
    function getCursorCoords(event) {
        let e = event || window.event;
        let coords_data = e, //璁板綍鍧愭爣鐨勬暟鎹�,榛樿涓� event 鏈韩,绉诲姩绔殑 touch 浼氫慨鏀�
            x,//x 杞�
            y;//y 杞�

        if (e["touches"] !== undefined) {
            if (e["touches"].length > 0) {
                coords_data = e["touches"][0];
            }
        }

        x = coords_data.clientX || coords_data.pageX;
        y = coords_data.clientY || coords_data.pageY;

        return { 'x': x, 'y': y }
    }

    /**
     * 妫€鏌ョЩ鍔ㄧ瑙︽懜婊戝姩鐨勪綅缃�
     */
    function checkNewPositionLimit(new_position) {
        if (-new_position > exzoom_img_ul_max_margin) {
            //闄愬埗鍚戝彸鐨勮寖鍥�
            new_position = -exzoom_img_ul_max_margin;
            imgIndex = 0;//鍚戝彸瓒呭嚭鑼冨洿鐨勫洖鍒扮涓€涓�
        } else if (new_position > 0) {
            //闄愬埗鍚戝乏鐨勮寖鍥�
            new_position = 0;
        }
        return new_position
    }

    /**
     * 缁戝畾鍚勭浜嬩欢
     */
    function bindingEvent() {
        //绉诲姩绔ぇ鍥惧尯鍩熺殑 touchend 浜嬩欢
        exzoom_img_ul.on("touchstart", function (event) {
            let coords = getCursorCoords(event);
            startX = coords.x;
            startY = coords.y;

            let left = exzoom_img_ul.css("left");
            exzoom_img_ul_position = parseInt(left);

            window.clearInterval(autoPlayInterval);//鍋滄鑷姩鎾斁
        });

        //绉诲姩绔ぇ鍥惧尯鍩熺殑 touchmove 浜嬩欢
        exzoom_img_ul.on("touchmove", function (event) {
            let coords = getCursorCoords(event);
            let new_position;
            endX = coords.x;
            endY = coords.y;

            //鍙窡闅忓厜鏍囩Щ鍔�
            new_position = exzoom_img_ul_position + endX - startX;
            new_position = checkNewPositionLimit(new_position);
            exzoom_img_ul.css("left", new_position);

        });

        //绉诲姩绔ぇ鍥惧尯鍩熺殑 touchend 浜嬩欢
        exzoom_img_ul.on("touchend", function (event) {
            //瑙﹀睆婊戝姩,鏍规嵁绉诲姩鏂瑰悜鎸夊€嶆暟瀵归綈鍏冪礌
            console.log(endX < startX);
            if (endX < startX) {
                //鍚戝乏婊戝姩
                moveRight();
            } else if (endX > startX) {
                //鍚戝彸婊戝姩
                moveLeft();
            }

            autoPlay();//鎭㈠鑷姩鎾斁
        });

        //澶у睆骞曞湪鏀惧ぇ鍖哄煙鐐瑰嚮,鍒ゆ柇鍚戝乏杩樻槸鍚戝彸绉诲姩
        exzoom_zoom_outer.on("mousedown", function (event) {
            let coords = getCursorCoords(event);
            startX = coords.x;
            startY = coords.y;

            let left = exzoom_img_ul.css("left");
            exzoom_img_ul_position = parseInt(left);
        });

        exzoom_zoom_outer.on("mouseup", function (event) {
            let offset = ele.offset();

            if (startX - offset.left < boxWidth / 2) {
                //鍦ㄦ斁澶ч暅鐨勫乏鍗婇儴鍒嗙偣鍑�
                moveLeft();
            } else if (startX - offset.left > boxWidth / 2) {
                //鍦ㄦ斁澶ч暅鐨勫彸鍗婇儴鍒嗙偣鍑�
                moveRight();
            }
        });

        //杩涘叆 exzoom 鍋滄鑷姩鎾斁
        ele.on("mouseenter", function () {
            window.clearInterval(autoPlayInterval);//鍋滄鑷姩鎾斁
        });
        //绂诲紑 exzoom 寮€濮嬭嚜鍔ㄦ挱鏀�
        ele.on("mouseleave", function () {
            autoPlay();//鎭㈠鑷姩鎾斁
        });

        //澶у睆骞曡繘鍏ュぇ鍥惧尯鍩�
        exzoom_zoom_outer.on("mouseenter", function () {
            exzoom_zoom.css("display", "block");
            exzoom_preview.css("display", "block");
        });

        //澶у睆骞曞湪澶у浘鍖哄煙绉诲姩
        exzoom_zoom_outer.on("mousemove", function (e) {
            let width_limit = exzoom_zoom.width() / 2,
                max_X = exzoom_zoom_outer.width() - width_limit,
                max_Y = exzoom_zoom_outer.height() - width_limit,
                current_X = e.pageX - exzoom_zoom_outer.offset().left,
                current_Y = e.pageY - exzoom_zoom_outer.offset().top,
                move_X = current_X - width_limit,
                move_Y = current_Y - width_limit;

            if (current_X <= width_limit) {
                move_X = 0;
            }
            if (current_X >= max_X) {
                move_X = max_X - width_limit;
            }
            if (current_Y <= width_limit) {
                move_Y = 0;
            }
            if (current_Y >= max_Y) {
                move_Y = max_Y - width_limit;
            }
            exzoom_zoom.css({ "left": move_X + "px", "top": move_Y + "px" });

            exzoom_preview_img.css({
                "left": -move_X * exzoom_preview.width() / exzoom_zoom.width() + "px",
                "top": -move_Y * exzoom_preview.width() / exzoom_zoom.width() + "px"
            });
        });

        //澶у睆骞曠寮€澶у浘鍖哄煙
        exzoom_zoom_outer.on("mouseleave", function () {
            exzoom_zoom.css("display", "none");
            exzoom_preview.css("display", "none");
        });

        //澶у睆骞曞厜瀹濊繘鍏ユ斁澶ч瑙堝尯鍩�
        exzoom_preview.on("mouseenter", function () {
            exzoom_zoom.css("display", "none");
            exzoom_preview.css("display", "none");
        });

        //缂╃暐鍥惧鑸�
        exzoom_next_btn.on("click", function () {
            moveRight();
        });
        exzoom_prev_btn.on("click", function () {
            moveLeft();
        });

        exzoom_navSpan.hover(function () {
            imgIndex = $(this).index();
            move(imgIndex);
        });
    }

    /**
     * 鑱氱劍鍦ㄥ鑸浘鐗囦笂,宸﹀彸绉诲姩閮戒細璋冪敤
     * @param direction: 鏂瑰悜,right | left,蹇呭～
     */
    function move(direction) {
        if (typeof direction === "undefined") {
            alert("exzoom 涓殑 move 鍑芥暟鐨� direction 鍙傛暟蹇呭～");
        }
        //濡傛灉瓒呭嚭鍥剧墖鏁伴噺浜�,杩斿洖绗竴寮�
        if (imgIndex > imgArr.length - 1) {
            imgIndex = 0;
        }

        //璁剧疆楂樹寒
        exzoom_navSpan.eq(imgIndex).addClass(navHightClass).siblings().removeClass(navHightClass);

        //鍒ゆ柇缂╃暐鍥惧鑸槸鍚﹂渶瑕侀噸鏂拌缃亸绉婚噺
        let exzoom_nav_width = exzoom_nav.width();
        let nav_item_width = g.navItemMargin + g.navWidth + g.navBorder * 2; // 鍗曚釜瀵艰埅鍏冪礌鐨勫搴�
        let new_nav_offset = 0;

        //鐩存帴瀵规瘮褰撳墠绱㈠紩鐨勫浘鐗囧崰鎹殑瀹藉害鍜宔xzoom鐨勫搴︾殑宸綔涓哄亸绉婚噺鍗冲彲
        let temp = nav_item_width * (imgIndex + 1);
        if (temp > exzoom_nav_width) {
            new_nav_offset = boxWidth - temp;
        }

        exzoom_nav_inner.css({
            "left": new_nav_offset
        });

        //鍒囨崲澶у浘
        let new_position = -boxWidth * imgIndex;
        //鍦� animate 鏂规硶鍓嶅厛璋冪敤 stop() ,閬垮厤鍙嶅簲杩熼挐
        new_position = checkNewPositionLimit(new_position);
        exzoom_img_ul.stop().animate({ "left": new_position }, 500);
        //澶勭悊鏀惧ぇ鍖哄煙
        previewImg(imgArr[imgIndex]);
    }

    /**
     * 瀵艰埅鍚戝彸
     */
    function moveRight() {
        imgIndex++;//鍏堝鍔� index,鍚庨潰鍒ゆ柇鑼冨洿
        if (imgIndex > imgNum) {
            imgIndex = imgNum;
        }
        move("right");
    }

    /**
     * 瀵艰埅鍚戝乏
     */
    function moveLeft() {
        imgIndex--;//鍏堝噺灏� index,鍚庨潰鍒ゆ柇鑼冨洿
        if (imgIndex < 0) {
            imgIndex = 0;
        }
        move("left");
    }

    /**
     * 鑷姩鎾斁
     */
    function autoPlay() {
        if (g.autoPlay) {
            autoPlayInterval = window.setInterval(function () {
                if (imgIndex >= imgNum) {
                    imgIndex = 0;
                }
                imgIndex++;
                move("right");
            }, g.autoPlayTimeout);
        }
    }

    /**
     * 棰勮鍥剧墖
     */
    function previewImg(image_prop) {
        if (image_prop === undefined) {
            return
        }
        exzoom_preview_img.attr("src", image_prop[0]);

        exzoom_main_img.attr("src", image_prop[0])
            .css({
                "width": image_prop[3] + "px",
                "height": image_prop[4] + "px"
            });
        exzoom_zoom_outer.css({
            "width": image_prop[3] + "px",
            "height": image_prop[4] + "px",
            "top": image_prop[5] + "px",
            "left": image_prop[6] + "px",
            "position": "relative"
        });
        exzoom_zoom.css({
            "width": image_prop[7] + "px",
            "height": image_prop[7] + "px"
        });
        exzoom_preview_img.css({
            "width": image_prop[8] + "px",
            "height": image_prop[9] + "px"
        });
    }

    /**
     * 鑾峰緱鍥剧墖鐨勭湡瀹炲昂瀵�
     * @param url
     * @param callback
     */
    function getImageSize(url, callback) {
        let img = new Image();
        img.src = url;

        // 濡傛灉鍥剧墖琚紦瀛橈紝鍒欑洿鎺ヨ繑鍥炵紦瀛樻暟鎹�
        if (typeof callback !== "undefined") {
            if (img.complete) {
                callback(img.width, img.height);
            } else {
                // 瀹屽叏鍔犺浇瀹屾瘯鐨勪簨浠�
                img.onload = function () {
                    callback(img.width, img.height);
                }
            }
        } else {
            return {
                width: img.width,
                height: img.height
            }
        }
    }

    /**
     * 璁＄畻鍥剧墖灞炴€�
     * @param image : jquery 瀵硅薄鎴� 鍥剧墖url鍦板潃
     * @param width : image 涓哄浘鐗噓rl鍦板潃鏃舵寚瀹氬搴�
     * @param height : image 涓哄浘鐗噓rl鍦板潃鏃舵寚瀹氶珮搴�
     * @returns {Array}
     */
    function copute_image_prop(image, width, height) {
        let src;
        let res = [];

        if (typeof image === "string") {
            src = image;
        } else {
            src = image.attr("src");
            let size = getImageSize(src);
            width = size.width;
            height = size.height;
        }

        res[0] = src;
        res[1] = width;
        res[2] = height;
        let img_scale = res[1] / res[2];

        if (img_scale === 1) {
            res[3] = boxHeight;//width
            res[4] = boxHeight;//height
            res[5] = 0;//top
            res[6] = 0;//left
            res[7] = boxHeight / 2;
            res[8] = boxHeight * 2;//width
            res[9] = boxHeight * 2;//height
            exzoom_nav_inner.append(`<span><img src="${src}" width="${g.navWidth}" height="${g.navHeight}"/></span>`);
        } else if (img_scale > 1) {
            res[3] = boxHeight;//width
            res[4] = boxHeight / img_scale;
            res[5] = (boxHeight - res[4]) / 2;
            res[6] = 0;//left
            res[7] = res[4] / 2;
            res[8] = boxHeight * 2 * img_scale;//width
            res[9] = boxHeight * 2;//height
            let top = (g.navHeight - (g.navWidth / img_scale)) / 2;
            exzoom_nav_inner.append(`<span><img src="${src}" width="${g.navWidth}" style='top:${top}px;' /></span>`);
        } else if (img_scale < 1) {
            res[3] = boxHeight * img_scale;//width
            res[4] = boxHeight;//height
            res[5] = 0;//top
            res[6] = (boxHeight - res[3]) / 2;
            res[7] = res[3] / 2;
            res[8] = boxHeight * 2;//width
            res[9] = boxHeight * 2 / img_scale;
            let top = (g.navWidth - (g.navHeight * img_scale)) / 2;
            exzoom_nav_inner.append(`<span><img src="${src}" height="${g.navHeight}" style="left:${top}px;"/></span>`);
        }

        return res;
    }

    // 闂寘缁撴潫     
})(jQuery, window);